---
title: HTTPS & TLS
layout: page
pageOrder: 7
section: 'General'
subsection: true
sitemap:
  priority: 0.7
  changefreq: 'monthly'
  lastmod: 2019-11-10T08:00:00+01:00
---

<p>MockServer uses port unification to simplify the configuration so all protocols (i.e. HTTP, HTTPS / SSL, SOCKS, etc) are supported on the same port.  This means when a request is sent over TLS (i.e. an HTTPS request) MockServer dynamically detects that the request is encrypted.</p>

<p>MockServer has support for TLS (i.e. HTTPS) in three areas:</p>

<ul>
    <li><strong>TLS for inbound connections</strong> to support HTTPS for mocking, proxying and control-plane interactions (creating expectations, retrieving logs, etc)</li>
    <li><strong>mTLS for inbound connections</strong> (also called client authentication or two-way TLS) to authenticate any client sending HTTPS requests</li>
    <li><strong>TLS for outbound connections</strong> (also called forward proxy TLS) to authenticate any client sending HTTPS requests</li>
</ul>

<p style="width: 100%; padding-top: 25px; padding-bottom: 25px;"><img src="../images/https_tls.png" alt="MockServer HTTPS & TLS" style="max-width:100%;"></p>

<p>The majority of HTTP clients perform the following steps when making an HTTPS request: </p>

<ol>
  <li>establish TCP connection to remote server</li>
    <li>perform TLS handshake with remote server and <a href="#verify_trust_chain"><strong>verify trust chain</strong></a> by receiving remote server X.509 Certificate and verifying it is signed by a known Certificate Authority</li>
  <li>perform <a href="#hostname_validation"><strong>hostname validation</strong></a> by comparing hostname (or IP address) of remote server with Subject Alternative Name (SAN) or Common Name (CN) on X.509</li>
</ol>

<p>MockServer is able to mock the behaviour of multiple hostnames (i.e. servers) and present a valid X.509 Certificates for them.  MockServer achieves this by dynamically generating its X.509 Certificate using an in-memory list of hostnames and ip addresses, this is <a href="#hostname_validation">described in more detail below</a>.</p>
<p>It is important to ensure that any client calling MockServer over TLS trust MockServer as a Certificate Authority (CA) (i.e. trust the MockServer CA X.509) the different approaches to establishing this trust is <a href="#verify_trust_chain">described below</a>.</p>

<p>MockServer provides multiple ways its TLS can be <a href="#configuration">configured</a>.  The following things can be configured:</p>

<ul>
    <li>How dynamic certificate are created including, hostname (i.e. <a href="#button_configuration_ssl_certificate_domain_name">CN</a> & <a href="#button_configuration_ssl_subject_alternative_name_domains">SAN</a>) and ip address (i.e. <a href="#button_configuration_ssl_subject_alternative_name_ips">SAN</a>)</li>
    <li>The Certificate Authority <a href="#button_configuration_tls_certificate_authority_certificate">X.509 Certificate</a> and <a href="#button_configuration_tls_certificate_authority_private_key">Private Key</a> used to sign all generated X.509</li>
    <li>Dynamic creation of a <a href="#button_configuration_dynamically_create_ca_certificate">unique (i.e. local) Certificate Authority X509 Certificate and Private Key</a> instead of using the fixed Certificate Authority X509 Certificate and Private Key in the <a href="https://github.com/mock-server/mockserver/blob/master/mockserver-core/src/main/resources/org/mockserver/socket/CertificateAuthorityCertificate.pem">git repo</a>.</li>
    <li>Require <a href="#button_configuration_require_mtls_for_all_tls_connections">mTLS (also called client authentication or two-way TLS)</a> for all TLS connections / HTTPS requests to MockServer</li>
    <li>Configure <a href="#button_configuration_trusted_tls_certs_group_for_proxied_reqs">trust store</a> and <a href="#button_configuration_forward_proxy_certificate_chain">client X.509</a> used during forwarded and proxied requests to endpoints requiring mTLS</li>
</ul>

<a id="verify_trust_chain" class="anchor" href="#verify_trust_chain">&nbsp;</a>

<h2>Ensure MockServer Certificates Are Trusted</h2>

<p>The MockServer CA X.509 must be considered a valid trust root to ensure MockServer's dynamically generate X.509 certificates are trusted by an HTTP Client.  This means the CA X.509 needs to be added into the JVM, HTTP Client or operating system as appropriate.</p>

<p>The MockServer CA X.509 can be found (in PEM format) in the <a href="https://github.com/mock-server/mockserver/blob/master/mockserver-core/src/main/resources/org/mockserver/socket/CertificateAuthorityCertificate.pem">MockServer github repo</a> or can be loaded from the classpath location <span class="constant">/org/mockserver/socket/CertificateAuthorityCertificate.pem</span></p>

<h3>Operating System</h3>

<p>It is possible to add the MockServer CA X.509 as a trusted root CA to your operating system, this will make most clients applications running on your OS (such as browsers) trust dynamically generated certificates from MockServer.</p>
<p>This is only an acceptable risk if it is done for a short period and the configuration setting <a href="#button_configuration_dynamically_create_ca_certificate">dynamicallyCreateCertificateAuthorityCertificate</a> is enabled to generate a local unique CA X.509 and Private Key that is saved to your local disk in the folder configured using <a href="#button_configuration_directory_to_save_dynamic_ssl_certificates">directoryToSaveDynamicSSLCertificate</a>.</p>
<p>If the configuration setting <a href="#button_configuration_dynamically_create_ca_certificate">dynamicallyCreateCertificateAuthorityCertificate</a> is not enabled, and your OS trusts the MockServer CA X.509, then this would leave your machine open to man-in-the-middle attacks because the corresponding Private Key is in the <a href="https://github.com/mock-server/mockserver/blob/master/mockserver-core/src/main/resources/org/mockserver/socket/CertificateAuthorityPrivateKey.pem">MockServer github repository</a>.  This would allow hackers to compromise all sensitive communicates such as to your bank or other sensitive sites.</p>

<h5>Web Browsers</h5>

<p>Browsers (such as Chrome, Firefox or IE) may not always trust dynamically generated certificates from MockServer because of <a href="https://tools.ietf.org/html/rfc6962">Certificate Transparency</a> and <a href="https://tools.ietf.org/html/rfc7469">Public Key Pinning</a> both of which make it hard to dynamically generate certificates that are trusted.</p>
<p>Some sites will work but others (such as google sites) won't work due to certificate pinning.</p>
<p>Browser that rely on <a href="https://tools.ietf.org/html/rfc6962">Certificate Transparency</a> will likely not trust dynamically generated certificates from MockServer</p>

<h3>Java via Classpath</h3>

<p>The following code shows how to load a file from the classpath or a relative filesystem location:</p>

<pre class="prettyprint lang-java code"><code class="code">public void doSomething() {
    String mockServerCA = loadFileFromLocation("/org/mockserver/socket/CertificateAuthorityCertificate.pem");
}

public String loadFileFromLocation(String location) {
    location = location.trim().replaceAll("\\\\", "/");

    Path path;
    if (location.toLowerCase().startsWith("file:")) {
        path = Paths.get(URI.create(location));
    } else {
        path = Paths.get(location);
    }

    if (Files.exists(path)) {
        // org.apache.commons.io.FileUtils
        return FileUtils.readFileToString(path.toFile(), "UTF-8");
    } else {
        return loadFileFromClasspath(location);
    }
}

private String loadFileFromClasspath(String location) {
    try {
        InputStream inputStream = this.getClass().getResourceAsStream(location);
        try {
            if (inputStream == null) {
                inputStream = this.getClass().getClassLoader().getResourceAsStream(location);
            }

            if (inputStream == null) {
                inputStream = ClassLoader.getSystemResourceAsStream(location);
            }

            if (inputStream != null) {
                try {
                    // org.apache.commons.io.IOUtils
                    return IOUtils.toString(inputStream, Charsets.UTF_8);
                } catch (IOException e) {
                    throw new RuntimeException("Could not read " + location + " from the classpath", e);
                }
            }

            throw new RuntimeException("Could not find " + location + " on the classpath");
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
    } catch (IOException ioe) {
        throw new RuntimeException("Exception closing input stream for " + location, ioe);
    }
}</code></pre>

<h3>Java DefaultSSLSocketFactory</h3>

<p>Another mechanism to ensure the MockServer X.509 is trusted is to configure the DefaultSSLSocketFactory in the JVM using the following line:</p>

<pre class="prettyprint lang-java code"><code class="code">HttpsURLConnection.setDefaultSSLSocketFactory(new KeyStoreFactory(new MockServerLogger()).sslContext().getSocketFactory());</code></pre>

<p>This can be used in a test case, as follows:</p>

<pre class="prettyprint lang-java code"><code class="code">import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockserver.integration.ClientAndServer;
import org.mockserver.logging.MockServerLogger;
import org.mockserver.socket.PortFactory;
import org.mockserver.socket.tls.KeyStoreFactory;

import javax.net.ssl.HttpsURLConnection;

public class ExampleTestClass {

    private static ClientAndServer mockServer;

    @BeforeClass
    public static void startMockServer() {
        // ensure all connection using HTTPS will use the SSL context defined by
        // MockServer to allow dynamically generated certificates to be accepted
        HttpsURLConnection.setDefaultSSLSocketFactory(new KeyStoreFactory(new MockServerLogger()).sslContext().getSocketFactory());
        mockServer = ClientAndServer.startClientAndServer(PortFactory.findFreePort());
    }

    @AfterClass
    public static void stopMockServer() {
        mockServer.stop();
    }

    @Test
    public void shouldDoSomething() {
        // test system
    }
}</code></pre>

<h3>Java Keytool</h3>

<p>The Java <strong>keytool</strong> command can also be used to add the MockServer CA X.509 certificate to the list of trust CA Certificates for a JVM, as follows:</p>

<pre class="prettyprint lang-java code"><code class="code">keytool -import -v -keystore /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts -alias mockserver-ca -file CertificateAuthorityCertificate.pem -storepass changeit -trustcacerts -noprompt</code></pre>

<p>An example bash script showing how this can be done can be found in the <a href="https://github.com/mock-server/mockserver/blob/master/scripts/install_ca_certificate.sh">MockServer github repo</a></p>

<a id="hostname_validation" class="anchor" href="#hostname_validation">&nbsp;</a>

<h2>Hostname Validation</h2>

<p>MockServer is able to mock the behaviour of multiple hostnames (i.e. servers) and present a valid X.509 Certificates for them.  MockServer achieves this by dynamically generating its X.509 Certificate using an in-memory list of hostnames and ip addresses.  When the list of hostnames or ips addresses changes a new certificate is generated.  The list of hostnames is updated, when:</p>

<ul>
  <li>configuration for SAN hostnames or SAN IP addresses is specified</li>
  <li>an expectation is added containing a Host header with a hostname not seen before</li>
  <li>a request is received containing a Host header with a hostname not seen before</li>
  <li>a TLS handshake using Server Name Indication (SNI) with a hostname not seen before</li>
</ul>

<p><strong>Note:</strong> if a request is received with a Host header for a hostname not seen before the first request will fail validation because the TLS connection has already been established before the Host header can be read, any subsequent requests with that hostname will pass hostname validation.</p>

<a id="configuration" class="anchor" href="#configuration">&nbsp;</a>

{% include_subpage _includes/tls_configuration.html %}